using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;
using mesoBoard.Data.Repositories;
using mesoBoard.Data;
using System.Web.Routing;
using mesoBoard.Web.Models;
using mesoBoard.Web.Core;
using mesoBoard.Web;
using mesoBoard.Services;
using System.IO;
using mesoBoard.Common;

namespace mesoBoard.Web.Controllers
{
    public partial class BoardController : mesoBoardController
    {
        public BoardController()
        {
            ViewData["TopBreadCrumb"] = "Board";
        }
        
        public ActionResult Index()
        {
            ViewData["BreadCrumb"] = "Board Index";
            Dictionary<int, bool> IsNew = new Dictionary<int, bool>();

            IEnumerable<Forum> forums = mbServices.Forums.GetViewableForums(CurrentUser.UserID);

            IEnumerable<ForumRow> rows = forums.Select(x => new ForumRow
            {
                Forum = x,
                HasNewPost = mbServices.Forums.HasNewPost(x.ForumID, CurrentUser.UserID),
            });

            ViewData["Forums"] = rows;
            IEnumerable<Category> cats = forums.Select(x=>x.Category).Distinct();
            return View(cats);
        }

        public ActionResult Search(string Keywords, int? Page)
        {
            Page = Page ?? 1;
            ViewData["TopBreadCrumb"] = "";
            ViewData["BreadCrumb"] = "Search";

            if (string.IsNullOrEmpty(Keywords))
            {
                return View();
            }
            else
            {
                List<SearchResult> Results = mbServices.Search.Lookup(Keywords, SearchType.TextAndTitle);

                if (Results.Count == 0)
                {
                    SetNotice("Search returned no results");
                    return View();
                }

                int CurrentPage = Page.Value;
                int PageCount = (int)Math.Ceiling(((decimal)Results.Count / 10));

                if (Results != null)
                {
                    Results = Results.Skip((CurrentPage - 1) * 10).Take(10).ToList();
                }

                RouteValueDictionary BaseValues = new RouteValueDictionary();
                BaseValues.Add("Keywords", Keywords);

                Paging pg = new Paging(Results.Count, 10, Page.Value, "Search", "Board", BaseValues);

                ViewData["Paging"] = pg;
                return View(Results);
            }
        }

        public ActionResult ViewForum(int ForumID, int? Page, bool? LastPost)
        {
            Forum TheForum = Repositories.Forums.GetForum(ForumID);
            UserPermissions UserPerms = new Models.UserPermissions(CurrentUser, TheForum);

            if (!UserPerms.Visible)
            {
                SetNotice("You can't view this forum");
                return RedirectToAction("Index", "Board");
            }


            Page = Page ?? 1;
            LastPost = LastPost ?? false;
            int ThreadCount = TheForum.TotalThreads;
            int PageSize =  SiteConfig.ThreadsPerPage.ToInt();
            int PageCount = (int)Math.Ceiling(((decimal)ThreadCount / PageSize));
            int CurrentPage = LastPost.Value ? PageCount : Page.Value;

            ViewData["BreadCrumb"] = TheForum.Name;

            RouteValueDictionary BaseValues = new RouteValueDictionary();
            BaseValues.Add("ForumID", ForumID);

            Paging forumPaging = new Paging(CurrentPage, PageCount, "ViewForum", "Board", BaseValues);

            IEnumerable<Thread> forumThreads = mbServices.Threads.GetPagedThreads(ForumID, CurrentPage, PageSize).Where(y => y.Type != 4);

            IEnumerable<ThreadRow> threadRows = forumThreads.Select(x => new ThreadRow
            {
                Thread = x,
                FirstPost = x.FirstPost,
                LastPost = x.LastPost,
                CurrentUser = CurrentUser,
                HasNewPost = mbServices.Threads.HasNewPost(x.ThreadID, CurrentUser.UserID),
                IsSubscribed = mbServices.Threads.IsSubscribed(x.ThreadID, CurrentUser.UserID)
            });

            IEnumerable<Thread> globalAnnouncements = mbServices.Threads.GetGlobalAnnouncements();

            IEnumerable<ThreadRow> gaThreads = globalAnnouncements.Select(x=> new ThreadRow
            {
                Thread = x,
                FirstPost = x.FirstPost,
                LastPost = x.LastPost,
                CurrentUser = CurrentUser,
                HasNewPost = mbServices.Threads.HasNewPost(x.ThreadID, CurrentUser.UserID),
                IsSubscribed = mbServices.Threads.IsSubscribed(x.ThreadID, CurrentUser.UserID)
            });

            ViewForum viewForum = new ViewForum
            {
                Forum = TheForum,
                ThreadRows = threadRows.ToList(),
                GlobalAnnouncements = gaThreads.ToList(),
                Paging = forumPaging,
                UserPermissions = UserPerms
            };

            return View(viewForum);
        }

        public ActionResult ViewThread(int ThreadID, int? Page, bool?LastPost, int? PostID)
        {
            Thread TheThread = mbServices.Threads.GetThread(ThreadID);

            if (!mbServices.Forums.CanView(TheThread.ForumID, CurrentUser.UserID) && TheThread.Type != 4)
            {
                SetNotice("You can't view this forum");
                return RedirectToAction("Index");
            }

            if (User.Identity.IsAuthenticated)
                mbServices.Threads.ThreadViewed(ThreadID, CurrentUser.UserID);

            Page = Page ?? 1;
            LastPost = LastPost ?? false;
            int PostCount = TheThread.TotalPosts;
            int PageSize = int.Parse(SiteConfig.PostsPerPage.Value);
            int PageCount = (int)Math.Ceiling(((decimal)PostCount / PageSize));
            int CurrentPage = LastPost.Value ? PageCount : Page.Value;

            if (PostID != null)
            {
                Post ThePost = mbServices.Posts.GetPost(PostID.Value);
                IEnumerable<Post> AllPosts = mbServices.Threads.GetPosts(ThreadID);
                int Position = AllPosts.ToList().IndexOf(ThePost) + 1;
                CurrentPage = (int)Math.Ceiling(((decimal)Position / PageSize));
            }


            RouteValueDictionary BaseValues = new RouteValueDictionary();
            BaseValues.Add("ThreadID", ThreadID);

            ViewData["BreadCrumb"] = TheThread.FirstPost.Title;
    
            Paging paging = new Paging(PostCount, PageSize, CurrentPage, "ViewThread", "Board", BaseValues); ;

            IEnumerable<Post> PagedPosts = mbServices.Posts.GetPagedPosts(ThreadID, CurrentPage, PageSize);
           
            IEnumerable<PostRow> postRows = PagedPosts.Select(x => new PostRow
            {
                Post = x,
                CurrentUser = CurrentUser,
                Thread = TheThread,
                CanEdit = mbServices.Posts.CanEditPost(x.PostID, CurrentUser.UserID),
                CanDelete = mbServices.Posts.CanDeletePost(x.PostID, CurrentUser.UserID),
                CanPost = mbServices.Forums.CanReply(TheThread.ForumID, CurrentUser.UserID),
            });

            Models.ViewThread vt = new ViewThread
            {
                Thread = TheThread,
                Posts = postRows,
                Paging = paging,
                CanCastVote = mbServices.Forums.CanCastVote(TheThread.ForumID, CurrentUser.UserID),
                HasVoted = mbServices.Polls.HasVoted(TheThread.ThreadID, CurrentUser.UserID),
                IsSubscribed = mbServices.Threads.IsSubscribed(TheThread.ThreadID, CurrentUser.UserID),
                ThreadActions = new ThreadActions 
                { 
                    CanLock=mbServices.Forums.CanLock(TheThread.ThreadID, CurrentUser.UserID),
                    CurrentUser = CurrentUser,
                    Thread =TheThread
                },
                CurrentUser = CurrentUser
            };

            return View(vt);
        }

        [Authorize]
        public ActionResult SubscribeToThread(int ThreadID)
        {
            mbServices.Threads.Subscribe(ThreadID, CurrentUser.UserID);

            SetSuccess("You have <b>subscribed</b> to this thread");

            return RedirectToAction("ViewThread", new { ThreadID = ThreadID });
        }

        [Authorize]
        public ActionResult UnsubscribeToThread(int ThreadID)
        {
            mbServices.Threads.Unsubscribe(ThreadID, CurrentUser.UserID);

            SetSuccess("You have been <b>unsubscribed</b> to this thread");

            return RedirectToAction("ViewThread", new { ThreadID = ThreadID });
        }

        [mbAuthorize(SpecialPermissions.Administrator, SpecialPermissions.Moderator)]
        public ActionResult LockThread(int ThreadID)
        {
            mbServices.Threads.Lock(ThreadID);
            SetSuccess("Thread locked");
            return RedirectToAction("ViewThread", new { ThreadID = ThreadID });
        }

        [mbAuthorize(SpecialPermissions.Administrator, SpecialPermissions.Moderator)]
        public ActionResult UnlockThread(int ThreadID)
        {
            mbServices.Threads.Unlock(ThreadID);
            SetSuccess("Thread unlocked");
            return RedirectToAction("ViewThread", new { ThreadID = ThreadID });
        }

        public ActionResult BoardStats()
        {
            List<OnlineUser> oUsers = Repositories.OnlineUsers.GetOnlineUsers().ToList();
            IEnumerable<OnlineGuest> oGuests = Repositories.OnlineUsers.GetOnlineGuests();

            IEnumerable<OnlineUserDetails> oUserDetails = null;
            if (oUsers.Count > 0)
            {
                oUserDetails = oUsers.Where(x=>x.User != null).Select(x => new OnlineUserDetails
                {
                    OnlineUser = x,
                    DefaultRole = x.User.UserProfile.DefaultRole.HasValue ? Repositories.Roles.GetRole(x.User.UserProfile.DefaultRole.Value) : null
                });
            }

            ViewData["OnlineUserDetails"] = oUserDetails;
            ViewData["OnlineUsers"] = oUsers;
            ViewData["OnlineGuests"] = oGuests;
            ViewData["TotalUsers"] = Repositories.Users.TotalUsers();
            ViewData["NewestUser"] = Repositories.Users.NewestUser();
            ViewData["TotalPosts"] = Repositories.Posts.TotalPosts();
            ViewData["TotalThreads"] = Repositories.Threads.TotalThreads();
            ViewData["BoardCreateDate"] =  SiteConfig.BoardCreateDate.Value;
            return View();
        }
    }
}
